package pers.cz.javacvdemo;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import java.io.File;

/**
 * @version 1.0
 * @description:
 * @author: ChengZhi 0336
 * @create: 2025-08-12 15:21
 **/
public class VideoToM3U8Converter {
	private static final String inputFilePath = "C:\\Users\\chengzhi\\Desktop\\temp\\4ktest.mp4";
	private static final String outputFilePath = "C:\\Users\\chengzhi\\Desktop\\temp\\output\\4ktest.m3u8";

	public static void main(String[] args) throws FrameGrabber.Exception, FrameRecorder.Exception {

		// 创建输出目录
		createOutputDirectory();

		// 设置FFmpeg日志级别
		avutil.av_log_set_level(avutil.AV_LOG_INFO);
		FFmpegLogCallback.set();

		// 创建FFmpegFrameGrabber对象
		FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFilePath);
		grabber.start();

		// 打印视频信息
		printVideoInfo(grabber);

		// 创建FFmpegFrameRecorder对象
		FFmpegFrameRecorder recorder = createRecorder(outputFilePath, grabber);

		// 启动录制
		recorder.start();

		// 读取视频帧并写入录制器
		Frame frame;
		int frameCount = 0;
		long startTime = System.currentTimeMillis();

		while ((frame = grabber.grab()) != null) {
			recorder.record(frame);
			frameCount++;

			// 显示进度
			if (frameCount % 300 == 0) {
				long currentTime = System.currentTimeMillis();
				double elapsed = (currentTime - startTime) / 1000.0;
				System.out.printf("已处理 %d 帧，耗时 %.2f 秒%n", frameCount, elapsed);
			}
		}

		// 停止录制和抓取
		recorder.stop();
		recorder.release();
		grabber.stop();
		grabber.release();

		System.out.println("视频已成功转换为m3u8格式！");
		System.out.println("总共处理了 " + frameCount + " 帧");

		// 验证输出文件
		verifyOutputFiles();
	}

	private static void createOutputDirectory() {
		File outputFile = new File(outputFilePath);
		File outputDir = outputFile.getParentFile();

		if (outputDir != null && !outputDir.exists()) {
			if (outputDir.mkdirs()) {
				System.out.println("创建输出目录: " + outputDir.getAbsolutePath());
			} else {
				throw new RuntimeException("无法创建输出目录: " + outputDir.getAbsolutePath());
			}
		}
	}

	private static void printVideoInfo(FFmpegFrameGrabber grabber) {
		System.out.println("视频信息:");
		System.out.println("分辨率: " + grabber.getImageWidth() + "x" + grabber.getImageHeight());
		System.out.println("帧率: " + grabber.getVideoFrameRate());
		System.out.println("视频比特率: " + grabber.getVideoBitrate());
		System.out.println("音频通道: " + grabber.getAudioChannels());
		System.out.println("音频采样率: " + grabber.getSampleRate());
		System.out.println("音频比特率: " + grabber.getAudioBitrate());
		System.out.println("时长: " + grabber.getLengthInTime() / 1000000 + "秒");
	}

	private static FFmpegFrameRecorder createRecorder(String outputFilePath, FFmpegFrameGrabber grabber) {
		FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFilePath,
				grabber.getImageWidth(),
				grabber.getImageHeight());

		// 基本配置
		recorder.setFormat("hls");

		// 视频配置
		recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
		recorder.setVideoBitrate(grabber.getVideoBitrate());
		recorder.setFrameRate(grabber.getVideoFrameRate());
		recorder.setGopSize((int) grabber.getVideoFrameRate());
		recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);

		// 编码器优化配置
		recorder.setOption("preset", "fast");
		recorder.setOption("tune", "zerolatency");
		recorder.setOption("profile", "baseline");
		recorder.setOption("level", "3.1");

		// 音频配置 - 使用正确的方法
		if (grabber.getAudioChannels() > 0) {
			recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
			recorder.setAudioChannels(grabber.getAudioChannels());
			recorder.setAudioBitrate(grabber.getAudioBitrate());

			// 使用 setAudioOption 设置采样率
			recorder.setAudioOption("ar", String.valueOf(grabber.getSampleRate()));

			// 设置音频质量
			recorder.setAudioQuality(0); // 最高质量
		}

		// HLS配置
		recorder.setOption("hls_time", "10");
		recorder.setOption("hls_list_size", "0");
		recorder.setOption("hls_wrap", "0");
		recorder.setOption("hls_flags", "delete_segments");
		recorder.setOption("hls_segment_filename", "C:\\Users\\chengzhi\\Desktop\\temp\\output\\" + "segment_%03d.ts");

		// 其他优化配置
		recorder.setOption("g", "60");
		recorder.setOption("keyint_min", "30");
		recorder.setOption("sc_threshold", "0");

		return recorder;
	}

	private static void verifyOutputFiles() {
		File outputFile = new File(outputFilePath);
		File outputDir = outputFile.getParentFile();

		if (outputFile.exists()) {
			System.out.println("✓ m3u8文件已生成: " + outputFile.getAbsolutePath());

			// 检查分片文件
			File[] tsFiles = outputDir.listFiles((dir, name) -> name.endsWith(".ts"));
			if (tsFiles != null && tsFiles.length > 0) {
				System.out.println("✓ 分片文件已生成: " + tsFiles.length + " 个");
				for (File tsFile : tsFiles) {
					System.out.println("  - " + tsFile.getName() + " (" + tsFile.length() + " bytes)");
				}
			} else {
				System.out.println("⚠ 未找到分片文件");
			}
		} else {
			System.out.println("❌ m3u8文件未生成");
		}
	}
}
